<template>
  <div>
      <el-tabs v-model="tabName"  type="card">
        <el-tab-pane label="对局统计" name="play">
          <div class="my-charts" >
            <div id="gameWinChart" style="width:400px;height:300px;"></div>
            <!--      450的宽度更能体现开局名-->
            <div id="openingChart" style="width:450px;height:300px;"></div>
            <div id="timeChart" style="width:400px;height:300px;"></div>

          </div>
          <div class="my-charts" >
            <div id="activityChart" style="width:1280px;height:300px;margin-top: 5px" ></div>
          </div>
        </el-tab-pane>
        <el-tab-pane label="ELO月度走势" name="elo">
          <div class="my-charts" >
            <div id="eloChart" style="width:1280px;height:500px;"></div>
          </div>

        </el-tab-pane>
        <el-tab-pane label="Rapid月K线" name="rapidK">
          <div class="my-charts" >
            <div id="rapidK" style="width:1280px;height:500px;"></div>
          </div>

        </el-tab-pane>
        <el-tab-pane label="Blitz月K线" name="Blitz月K线K">
          <div class="my-charts" >
            <div id="blitzK" style="width:1280px;height:500px;"></div>
          </div>

        </el-tab-pane>
        <el-tab-pane label="Bullet月K线" name="bulletK">
          <div class="my-charts" >
            <div id="bulletK" style="width:1280px;height:500px;"></div>
          </div>

        </el-tab-pane>

        <el-tab-pane label="Classic月K线" name="ClassicK">
          <div class="my-charts" >
            <div id="classicK" style="width:1280px;height:500px;"></div>
          </div>

        </el-tab-pane>
      </el-tabs>

  </div>
</template>

<script>

import {invoke} from "@/lib/utils";
import Chessmate from "@/lib/chessmate";
import path from "path";
import fs from "fs";
import Sqlite from "@/lib/sqlite";
import Database from "@/lib/database";
import moment from "moment/moment";
import * as echarts from 'echarts';
import _ from "lodash";

export default {
  name: "Chart",
  data() {
    return {
      gameData: [],
      gameWinData: [], // 黑白胜率统计
      openingData: [], // 开局
      timeData: [],
      winChart: null,  // 胜率图
      openingChart: null, // 开局分布
      timChart: null, //时间分布
      lichessUserName: '',
      tabName: 'play',
      activityData: [],
      activityMonth: [],
      activityChart: null, // 每月活跃图
      // 积分折线图
      eloChart: null,
      eloData: [],
      eloRapid: [],
      eloBlitz: [],
      eloBullet: [],
      eloClassic: [],
      eloRapidK: [],
      eloBlitzK: [],
      eloBulletK: [],
      eloClassicK: [],
      eloMonth: [],
      rapidK: null,
      bulletK: null,
      blitzK: null,
      classicK: null,
    }
  },
  props: {

  },
  methods: {
    async getSetting() {
      this.appPath = await invoke('getCurrentPath', null)
      let config = await invoke('get', {name: 'setting', type: 'database'})
      this.lichessUserName = config.lichessUserName
      this.pluginPath = config.pluginPath
      this.dbFolderPath = config.dbFolderPath
      const chessConfig = {
        path: config.enginePath,
        analyzeSpeed: config.analyzeSpeed,
        blunderThreshold: config.blunderThreshold,
        mistakeThreshold: config.mistakeThreshold,
      }
      this.exportFilePath = config.exportFilePath || './'
      await Chessmate.init(chessConfig)
    },
    // 检查user.db是否存在于用户目录 不存在则复制
    async checkUserDb() {
      const userCachePath = await invoke('getUserDataPath', null)
      const userDbPath = path.join(userCachePath, './chessmate/user.db')
      const dbDir = path.join(userCachePath, './chessmate')
      const backUpDBPath = path.join(this.dbFolderPath, './user.db')
      if (!fs.existsSync(backUpDBPath)) {
        return this.$notify({duration: 1000, title: '通知', message: "备份数据未找到，请联系开发者", type: 'error'})
      }
      // 理论上这个文件夹只要程序打开就一定存在
      if (!fs.existsSync(dbDir)) {
        fs.mkdirSync(dbDir)
      }
      if (!fs.existsSync(userDbPath)) {
        fs.copyFileSync(backUpDBPath, userDbPath)
        this.$notify({duration: 1000, title: '通知', message: "已经成功初始化用户数据", type: 'success'})
      }
      await Sqlite.connectUser(userDbPath)
      await this.getGameData()
    },
    async getGameData() {
      const res = await Database.getAllUserGame()
      this.gameData = res
      for (const item of this.gameData) {
        item.gameDate = moment(Number(item.gameDate)).format('YYYY-MM-DD HH:mm:ss')
        item.analyzed = item.analyzed === 0 ? '否' : '是'
      }
      console.log("this.gameData", this.gameData)
    },
    // 处理数据
    handleGameData() {
      this.gameWinData = []
      this.openingData = []
      const openingMap = {}
      const timeMap = {}
      let blackWin = 0
      let whiteWin = 0
      let blackLose = 0
      let whiteLose = 0
      let draw = 0

      this.timeData = []
      this.activityMonth = []
      this.activityData = []
      this.eloData = []
      this.eloRapid = []
      this.eloBlitz = []
      this.eloBullet = []
      this.eloClassic = []
      this.eloRapidK = []
      this.eloBlitzK = []
      this.eloBulletK = []
      this.eloClassicK = []
      this.eloMonth = []

      const activityMap = {}
      const eloMap = {}
      let myElo =0
      for (const game of this.gameData) {
        const {black, white, result, opening, time, gameDate, blackElo, whiteElo, type} = game
        const yearMonth = moment(gameDate, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM')
        const day = Number(moment(gameDate, 'YYYY-MM-DD HH:mm:ss').format('DD'))
        if (!activityMap[yearMonth]) activityMap[yearMonth] = 0
        activityMap[yearMonth]++

        // 将开局拆分
        let openingArr = opening.split(':')
        let openingHead = openingArr[0]
        let headSplit = openingHead.split(' ')
        headSplit.shift()
        let realOpening = ''
        for(const item of headSplit) {
          realOpening += item + ' '
        }
        realOpening = realOpening.slice(0, realOpening.length -1)
        if (!openingMap[realOpening]) openingMap[realOpening] = 0
        openingMap[realOpening]++
        if (!timeMap[time]) timeMap[time] = 0
        timeMap[time]++
        if (result === '1/2-1/2') {
          draw++
        } else {
          if (black === this.lichessUserName) {
            myElo = Number(blackElo)
            if (result === '1-0') {
              blackLose++
            } else {
              blackWin++
            }
          }
          if (white === this.lichessUserName) {
            myElo = Number(whiteElo)
            if (result === '1-0') {
              whiteWin++
            } else {
              whiteLose++
            }
          }
        }
        let realType = null
        if (type.toLowerCase().indexOf('rapid') !== -1) {
          realType = 'rapid'
        } else if (type.toLowerCase().indexOf('bullet') !== -1) {
          realType = 'bullet'
        } else if (type.toLowerCase().indexOf('blitz') !== -1) {
          realType = 'blitz'
        } else if (type.toLowerCase().indexOf('classic') !== -1) {
          realType = 'classic'
        }
        if (realType === 'rapid' || realType === 'classic' || realType === 'bullet' || realType === 'blitz') {
          // 处理积分数据
          if (!eloMap[yearMonth]) {
            eloMap[yearMonth] = {
              rapid: {eloList: [], max: 0, min: 100000, first: 0, end: 0, firstDay: 31, endDay: 0},
              classic: {eloList: [], max: 0, min: 100000, first: 0, end: 0, firstDay: 31, endDay: 0},
              bullet: {eloList: [], max: 0, min: 100000, first: 0, end: 0, firstDay: 31, endDay: 0},
              blitz: {eloList: [], max: 0, min: 100000, first: 0, end: 0, firstDay: 31, endDay: 0},
            }
          }
          eloMap[yearMonth][realType].eloList.push(myElo)
          eloMap[yearMonth][realType].max = eloMap[yearMonth][realType].max > myElo ? eloMap[yearMonth][realType].max : myElo
          eloMap[yearMonth][realType].min = eloMap[yearMonth][realType].min < myElo ? eloMap[yearMonth][realType].min : myElo
          if (eloMap[yearMonth][realType].firstDay > day) {
            eloMap[yearMonth][realType].firstDay = day
            eloMap[yearMonth][realType].first = myElo
          }
          if (eloMap[yearMonth][realType].endDay <= day) {
            eloMap[yearMonth][realType].endDay = day
            eloMap[yearMonth][realType].end = myElo
          }
        }
      }

      console.log("eloMap", eloMap)
      this.gameWinData.push({value: whiteWin, name: '白胜'})
      this.gameWinData.push({value: whiteLose, name: '白负'})
      this.gameWinData.push({value: blackWin, name: '黑胜'})
      this.gameWinData.push({value: blackLose, name: '黑负'})
      this.gameWinData.push({value: draw, name: '平局'})
      for (const opening in openingMap) {
        this.openingData.push({value: openingMap[opening], name: opening})
      }
      for (const time in timeMap) {
        this.timeData.push({value: timeMap[time], name: time})
      }
      this.openingData = _.orderBy(this.openingData, 'value', 'desc')
      this.openingData = this.dropLongData(this.openingData)
      this.timeData = _.orderBy(this.timeData, 'value', 'desc')
      this.timeData = this.dropLongData(this.timeData)
      for (const act in activityMap) {
        this.activityMonth.push(act)
      }
      for (const item of this.activityMonth) {
        this.activityData.push(activityMap[item])
      }
      // 处理积分和K线
      let averageRapidLast = 0
      let averageClassicLast = 0
      let averageBlitzLast = 0
      let averageBulletLast = 0
      for (const monthDay in eloMap) {
        this.eloMonth.push(monthDay)
        const {rapid, classic, blitz, bullet} = eloMap[monthDay]
        if (rapid) {
          const {first, end, max, min} = rapid
          if (first && end && max && min) {
            this.eloRapidK.push([first, end, min, max])
          } else {
            this.eloRapidK.push(this.eloRapidK[this.eloRapidK.length - 1])
          }
        }
        if (classic) {
          const {first, end, max, min} = classic
          if (first && end && max && min) {
            this.eloClassicK.push([first, end, min, max])
          } else {
            this.eloClassicK.push(this.eloClassicK[this.eloClassicK.length - 1])
          }
        }
        if (blitz) {
          const {first, end, max, min} = blitz
          if (first && end && max && min) {
            this.eloBlitzK.push([first, end, min, max])
          } else {
            this.eloBlitzK.push(this.eloBlitzK[this.eloBlitzK.length - 1])
          }
        }
        if (bullet) {
          const {first, end, max, min} = bullet
          if (first && end && max && min) {
            this.eloBulletK.push([first, end, min, max])
          } else {
            this.eloBulletK.push(this.eloBulletK[this.eloBulletK.length - 1])
          }
        }

        let averageRapid = 0
        let averageClassic = 0
        let averageBlitz = 0
        let averageBullet = 0
        if (rapid.eloList.length) {
          for (const score of rapid.eloList) {
            averageRapid += score
          }
          averageRapid = averageRapid / rapid.eloList.length
          averageRapid = parseInt(Number(averageRapid.toFixed(2)))
          this.eloRapid.push(averageRapid || averageRapidLast || 0)
          averageRapidLast = averageRapid
        } else {
          this.eloRapid.push( this.eloRapid[this.eloRapid.length - 1])
        }
        if (bullet.eloList.length) {
          for (const score of bullet.eloList) {
            averageBullet += score
          }
          averageBullet = averageBullet / bullet.eloList.length
          averageBullet = parseInt(Number(averageBullet.toFixed(2)))
          this.eloBullet.push(averageBullet || averageBulletLast || 0)
          averageBulletLast = averageBullet
        } else {
          this.eloBullet.push( this.eloBullet[this.eloBullet.length - 1])
        }
        if (blitz.eloList.length) {
          for (const score of blitz.eloList) {
            averageBlitz += score
          }
          averageBlitz = averageBlitz / blitz.eloList.length
          averageBlitz = parseInt(Number(averageBlitz.toFixed(2)))
          this.eloBlitz.push(averageBlitz || averageBlitzLast || 0)
          averageBlitzLast = averageBlitz
        } else {
          this.eloBlitz.push( this.eloBlitz[this.eloBlitz.length - 1])
        }
        if (classic.eloList.length) {
          for (const score of classic.eloList) {
            averageClassic += score
          }
          averageClassic = averageClassic / classic.eloList.length
          averageClassic = parseInt(Number(averageClassic.toFixed(2)))
          this.eloClassic.push(averageClassic || averageClassicLast || 0)
          averageClassicLast = averageClassic
        } else {
          this.eloClassic.push( this.eloClassic[this.eloClassic.length - 1])
        }
      }

    },
    // 超过10位的数据转换为其他
    dropLongData(data) {
      if (data.length > 10) {
        let other = 0
        for (let i =10;i<data.length;i++) {
          other+= data[i].value
        }
        data.length = 10
        data.push({name: '其他', value: other})
      }
      return data
    },
    init() {
      this.winChart = echarts.init(document.getElementById("gameWinChart"));
      this.winChart.setOption({
        title: {
          text: '胜率',
          left: 'center',
          top: 'center'
        },
        tooltip: {
          trigger: 'item',
        },
        series: [
          {
            type: 'pie',
            radius: [30, 100],
            center: ['50%', '50%'],
            roseType: 'area',
            itemStyle: {
              borderRadius: 8
            },
            data: this.gameWinData
          }
        ]
      });

      this.openingChart = echarts.init(document.getElementById("openingChart"));
      this.openingChart.setOption({
        title: {
          text: '开局',
          left: 'center',
          top: 'center'
        },
        tooltip: {
          trigger: 'item',
        },
        series: [
          {
            type: 'pie',
            radius: [30, 100],
            center: ['50%', '50%'],
            roseType: 'area',
            itemStyle: {
              borderRadius: 8
            },
            data: this.openingData
          }
        ]
      });

      this.timeChart = echarts.init(document.getElementById("timeChart"));
      this.timeChart.setOption({
        title: {
          text: '时间',
          left: 'center',
          top: 'center'
        },
        tooltip: {
          trigger: 'item',
        },
        series: [
          {
            type: 'pie',
            radius: [30, 100],
            center: ['50%', '50%'],
            roseType: 'area',
            itemStyle: {
              borderRadius: 8
            },
            data: this.timeData
          }
        ]
      });

      this.activityChart = echarts.init(document.getElementById("activityChart"));
      this.activityChart.setOption({
        title: {
          text: '每月对局数',

        },
        tooltip: {
          trigger: 'item',
        },
        xAxis: {
          type: 'category',
          data: this.activityMonth
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: this.activityData,
            type: 'bar'
          }
        ]
      });

      this.eloChart = echarts.init(document.getElementById("eloChart"));
      this.eloChart.setOption({
        title: {
          text: '月度ELO走势'
        },
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          data: ['Rapid', 'Blitz', 'Bullet', 'Classic']
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: this.eloMonth
        },
        yAxis: {
          type: 'value',
          interval: 500,
          splitNumber: 8,
        },
        series: [
          {
            name: 'Rapid',
            type: 'line',
            data: this.eloRapid,
            smooth: true
          },
          {
            name: 'Blitz',
            type: 'line',
            data: this.eloBlitz,
            smooth: true
          },
          {
            name: 'Bullet',
            type: 'line',
            data: this.eloBullet,
            smooth: true
          },
          {
            name: 'Classic',
            type: 'line',
            data: this.eloClassic,
            smooth: true
          },
        ]
      });

      this.rapidK = echarts.init(document.getElementById("rapidK"));
      this.rapidK.setOption({
        title: {
          text: '月度ELO走势'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          data: this.eloMonth
        },
        yAxis: {},
        series: [
          {
            type: 'candlestick',
            data: this.eloRapidK
          }
        ]
      });

      this.classicK = echarts.init(document.getElementById("classicK"));
      this.classicK.setOption({
        title: {
          text: '月度ELO走势'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          data: this.eloMonth
        },
        yAxis: {},
        series: [
          {
            type: 'candlestick',
            data: this.eloClassicK
          }
        ]
      });

      this.bulletK = echarts.init(document.getElementById("bulletK"));
      this.bulletK.setOption({
        title: {
          text: '月度ELO走势'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          data: this.eloMonth
        },
        yAxis: {},
        series: [
          {
            type: 'candlestick',
            data: this.eloBulletK
          }
        ]
      });

      this.blitzK = echarts.init(document.getElementById("blitzK"));
      this.blitzK.setOption({
        title: {
          text: '月度ELO走势'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          data: this.eloMonth
        },
        yAxis: {},
        series: [
          {
            type: 'candlestick',
            data: this.eloBlitzK
          }
        ]
      });
    },

  },
  async mounted() {
    await this.getSetting()
    await this.checkUserDb()
    this.handleGameData()
    this.init()
  },
  components: {

  },
  watch: {

  },
}
</script>


<style scoped>
.my-charts {
  display: flex;
  position: relative;
  > div {
    width: 250px;
    height: 200px;
    border: 1px solid #ccc;
  }
  div + div {
    margin-left: 10px;
  }
}


</style>